package com.jwcao.common.cast.operation.instance;

import com.jwcao.common.cast.annotation.CastConstructor;
import com.jwcao.common.cast.operation.access.AccessOperation;
import com.jwcao.common.scan.object.ScanClass;
import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * name: InstanceOperationFactory description: TODO
 *
 * @author caojingwei date: 2023/3/24 21:44
 */
public class InstanceOperationFactory {

    public static InstanceOperation get(String id, ScanClass targetClass, List<AccessOperation> accessOperationList) {
        Constructor[] constructors = targetClass.getClazz().getConstructors();

        for (Constructor constructor : constructors) {
            CastConstructor[] castConstructors = constructor.getAnnotationsByType(
                CastConstructor.class);
            if (ArrayUtils.isNotEmpty(castConstructors)) {
                CastConstructor castConstructor = Arrays.stream(castConstructors)
                    .filter(c -> StringUtils.equals(c.id(), id))
                    .findAny().orElse(null);

                if (castConstructor != null) {

                    Parameter[] parameters = constructor.getParameters();

                    List<AccessOperation> accessParameterList = Arrays.stream(parameters)
                        .map(p -> accessOperationList.stream()
                            .filter(accessOperation -> accessOperation.isTarget(p.getName())).findAny().orElse(null))
                        .collect(Collectors.toList());

                    return new ArgInstanceOperation(targetClass, accessParameterList);
                }
            }
        }

        return new NoArgInstanceOperation(targetClass);
    }
}
